package com.ruan.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruan.common.Code;
import com.ruan.common.Result;
import com.ruan.mapper.FileMapper;
import com.ruan.pojo.FileEntity;
import com.ruan.pojo.Project;
import com.ruan.service.FileService;
import com.ruan.service.ProjectService;
import com.ruan.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
@RestController
@RequestMapping("/upload")
public class FileUploadController {

    @Autowired
    ProjectService projectService;
    @Autowired
    FileService fileService;
    @Autowired
    FileMapper fileMapper;

    @Autowired
    private AliOSSUtils aliOSSUtils;

    @Value("${kejiu.path}")//必须是org.springframework.beans.factory.annotation提供的Value
    private String basePath;

    //云上传
    @PostMapping("/cloud/upload")
    public Result upload(@RequestParam("file") MultipartFile file,
                         @RequestParam("projectId") Long projectId,
                         @RequestParam("employeeId") Long employeeId) throws IOException {
        log.info("文件上传, 文件名: {}", file.getOriginalFilename());

        //调用阿里云OSS工具类进行文件上传
        String url = aliOSSUtils.upload(file,projectId,employeeId);
        log.info("文件上传完成,文件访问的url: {}", url);

        return new Result(Code.SAVE_OK,url,"文件上传成功");
//        return Result.success(url);
    }

    //本地存储文件
    /*@PostMapping("/upload")
    public Result upload(String username , Integer age , MultipartFile image) throws Exception {
        log.info("文件上传: {}, {}, {}", username, age, image);
        //获取原始文件名 - 1.jpg  123.0.0.jpg
        String originalFilename = image.getOriginalFilename();

        //构造唯一的文件名 (不能重复) - uuid(通用唯一识别码) de49685b-61c0-4b11-80fa-c71e95924018
        int index = originalFilename.lastIndexOf(".");
        String extname = originalFilename.substring(index);
        String newFileName = UUID.randomUUID().toString() + extname;
        log.info("新的文件名: {}", newFileName);

        //将文件存储在服务器的磁盘目录中 D:\images
        image.transferTo(new File("D:\\images\\"+newFileName));

        return Result.success();
    }*/

    //    private final String UPLOAD_DIR = "D:/DLSS";
//    当用户上传文件时，Spring框架会将上传的文件暂存到内存或磁盘的临时位置，
//    并将其封装成MultipartFile对象。在处理文件上传的方法中，可以通过MultipartFile
//    对象来获取上传文件的内容、文件名、大小等信息，并进一步处理这些文件数据。
    @PostMapping("/upload")//(io流的transferTo方法实现)
    public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file,
                                                   @RequestParam("projectId") Long projectId,
                                                   @RequestParam("employeeId") Long employeeId) {
        System.out.println("handleFileUpload传来的参数是：file:"+file+"projectId:"+projectId+"employeeId:"+employeeId);
        FileEntity fileEntity = new FileEntity();
        fileEntity.setFileName(file.getOriginalFilename());
        fileEntity.setEmployeeId(employeeId);//组长可以查到是谁上传的
        fileEntity.setProjectId(projectId);//组长可以查看该项目
        fileService.save(fileEntity);//存入数据库，要的时候组长再根据这个下载
        // 获取上传文件的原始文件名
        String originalFilename = file.getOriginalFilename();
        System.out.println("源文件名是："+originalFilename);

        // 获取文件后缀名
        String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);

        // 判断(后缀名)文件类型是否符合要求.doc,.docx,.txt,.xls,.xlsx,.zip,.rar,.7z,.html,.css,.xml,.pdf,.mp3
        if ("doc".equals(fileType) || "docx".equals(fileType)  || "txt".equals(fileType)
                || "xls".equals(fileType)  || "xlsx".equals(fileType)  || "zip".equals(fileType)
            || "rar".equals(fileType)  || "7z".equals(fileType)  || "html".equals(fileType)
                || "css".equals(fileType)  || "xml".equals(fileType)  || "pdf".equals(fileType)
                || "mp3".equals(fileType)){
// 保存文件到指定目录
            try {
                //文件上传后的目标路径。basePath
//                File destFile = new File("D:\\DLSS\\" + originalFilename);
                File destFile = new File(basePath + originalFilename);

                //通过file.transferTo(destFile)方法将上传的文件保存到目标路径中。
                //文件首先会被存储在服务器的临时目录中。然后通过transferTo()
                //方法，将文件内容从临时目录移动或复制到目标路径中。
                file.transferTo(destFile);
                return ResponseEntity.ok("文件上传成功");
            } catch (IOException e) {
                e.printStackTrace();
                return ResponseEntity.badRequest().body("文件保存失败");
            }
        } else {
            // 文件类型不符合要求，返回错误信息
            return ResponseEntity.badRequest().body("只能上传.doc,.docx,.txt,.xls," +
                    ".xlsx,.zip,.rar,.7z,.html,.css,.xml,.pdf,.mp3格式的文件");
        }
    }


    //下载按钮的消失与出现
    @GetMapping("/canDownload/{projectId}")
    public Result canDownload(@PathVariable Long projectId,
                              @RequestParam("employeeId") Long employeeId){
//        @RequestParam("employerId") Long employerId,
        LambdaQueryWrapper<FileEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FileEntity::getProjectId, projectId);
        queryWrapper.eq(FileEntity::getEmployeeId, employeeId);//组员id匹配
        List<FileEntity> fileEntityList = fileMapper.selectList(queryWrapper);
        System.out.println("fileEntityList是null还是''"+fileEntityList);
        if (fileEntityList.isEmpty()){
            System.out.println("fileEntityList是Empty");
            return new Result(Code.SELECT_ERR,"");
        }
        System.out.println("fileEntityList不是null");
        return new Result(Code.SELECT_OK,"");
    }

//    1.使用FileInputStream和FileOutputStream：通过创建FileInputStream来读取文件内容，
//    然后使用FileOutputStream将文件内容写入到目标位置，实现文件的上传和下载。
    //下载成压缩包
    @GetMapping("/download/{projectId}")
    public ResponseEntity<Resource> getFile(@PathVariable Long projectId,
                                            @RequestParam("employerId") Long employerId,
                                            @RequestParam("employeeId") Long employeeId) {
        // 根据projectId和员工id获取文件信息
        //        FileEntity fileEntity = fileService.getProjectByIdAndEmployeeId(projectId,employeeId);

        LambdaQueryWrapper<FileEntity> queryWrapper = new LambdaQueryWrapper<>();
        //哪个项目
        queryWrapper.eq(FileEntity::getProjectId, projectId);
        //下载的是这个组员的文件
        queryWrapper.eq(FileEntity::getEmployeeId, employeeId);//组员id匹配
        List<FileEntity> fileEntityList = fileMapper.selectList(queryWrapper);
        if (fileEntityList != null && !fileEntityList.isEmpty()) {
            // 创建临时目录用于存放要下载的文件basePath
//            File tempDir = new File("D:\\tempDir");
            File tempDir = new File(basePath + "tempDir");
            if (!tempDir.exists()) {
                tempDir.mkdirs();
            }
            //存放即将压缩的所有文件
            List<File> filesToZip = new ArrayList<>();
            for (FileEntity fileEntity : fileEntityList) {
                Project project = projectService.getById(fileEntity.getProjectId());
                //project.getEmployeeId() == employerId我是组长。。。
                if (project != null && project.getEmployeeId() == employerId) {
//                    String filePath = "D:\\DLSS\\" + fileEntity.getFileName();
                    String filePath = basePath + fileEntity.getFileName();

                    File file = new File(filePath);//即将操作的文件
                    // 如果文件存在且为文件类型
                    if (file.exists() && file.isFile()) {
                        //创建一个目标文件destFile，这个目标文件是在临时目录（tempDir）下，目标文件destFile的文件名就是原文件名
                        File destFile = new File(tempDir, fileEntity.getFileName());
                        try {
                            //将一个文件从源路径复制到目标路径(Files是一个类)
                            //将file表示的文件(原文件)复制到destFile表示的目标路径中
                            Files.copy(file.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                            //如果目标路径已经存在同名文件，如果目标文件不存在，则会创建一个新的文件并将源文件内容复制过去。
                            filesToZip.add(destFile);
                            //一个个的存文件进去，以便后续的压缩
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            //即将压缩的文件列表拿到文件了。。。
            if (!filesToZip.isEmpty()) {
                // 创建压缩文件
//                String zipFilePath = "D:\\tempDir\\downloadedFiles.zip";
                String zipFilePath = basePath + "tempDir\\downloadedFiles.zip";

                try (FileOutputStream fos = new FileOutputStream(zipFilePath);
                    //通过 ZipOutputStream 将压缩文件的输出流 fos 进行初始化，
                     // 这个输出流指向要生成的ZIP文件。
                     ZipOutputStream zos = new ZipOutputStream(fos)) {
                    //遍历filesToZip列表中的每个文件fileToZip
                    for (File fileToZip : filesToZip) {
                        //对于每个文件，创建一个ZipEntry对象zipEntry，
                        //表示ZIP文件中的一个条目，其名称为当前文件的名称。
                        ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
                        //使用zos.putNextEntry(zipEntry)来开始写入新的ZIP文件条目
                        zos.putNextEntry(zipEntry);
                        //调用Files.copy()方法
                        //将当前文件的内容复制到ZipOutputStream中，
                        //实现将文件内容写入ZIP文件的功能。
                        Files.copy(fileToZip.toPath(), zos);
                        //结束当前ZIP文件条目的写入
                        zos.closeEntry();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return ResponseEntity.badRequest().body(null);
                }

                // 提供压缩文件给组长下载
                try {
                    //通过UrlResource创建一个资源对象resource，表示要下载的ZIP文件的路径
                    Resource resource = new UrlResource(Paths.get(zipFilePath).toUri());
                    //      资源存在                 资源可读
                    if (resource.exists() && resource.isReadable()) {
                        //将资源作为响应体返回，实现文件下载功能
                        return ResponseEntity.ok()
                                .header(HttpHeaders.CONTENT_DISPOSITION,
                                        "attachment; filename=\"downloadedFiles.zip\"")
                                .body(resource);
                        //设置响应头Content-Disposition为attachment
                        //浏览器下载文件时使用的文件名是downloadedFiles
                    } else {
                        //404 Not Found
                        return ResponseEntity.notFound().build();
                    }
                    //资源路径不合法
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    //返回400 Bad Request
                    return ResponseEntity.badRequest().body(null);
                }
            } else {
                return ResponseEntity.notFound().build();
            }
        } else {
            return ResponseEntity.notFound().build();
        }
    }


//    @GetMapping("/download/{fileName}")
    // 在访问文件时，进行权限验证
//    @GetMapping("/download/{projectId}")
//    public ResponseEntity<Resource> getFile(@PathVariable Long projectId,
//                                            @RequestParam("employerId") Long employerId,
//                                            @RequestParam("employeeId") Long employeeId) {
//        // 根据projectId和员工id获取文件信息
//        //        FileEntity fileEntity = fileService.getProjectByIdAndEmployeeId(projectId,employeeId);
//
//        LambdaQueryWrapper<FileEntity> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(FileEntity::getProjectId,projectId);
//        queryWrapper.eq(FileEntity::getEmployeeId,employeeId);//组员id匹配
////        FileEntity fileEntity = fileMapper.selectOne(queryWrapper);
////        List<FileEntity> fileEntityList = fileMapper.selectList(queryWrapper);
//        //暂时只能上传和下载一个文件
//        if (fileEntityList != null) {
////            for(FileEntity fileEntity : fileEntityList){
//
//            // 获取文件的项目信息，包括组长ID
//            Project project = projectService.getById(fileEntity.getProjectId());
//            if (project != null && project.getEmployeeId() == employerId) {
//                // 验证员工是否为项目组长，允许访问文件
//                String filePath = "D:\\DLSS\\" + fileEntity.getFileName();
//                System.out.println("下载的文件是："+filePath);
//                try {
//                    Resource resource = new UrlResource(Paths.get(filePath).toUri());
//                    if (resource.exists() && resource.isReadable()) {
//                        return ResponseEntity.ok()
//                                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
//                                .body(resource);
//                    } else {
//                        return ResponseEntity.notFound().build();
//                    }
//                } catch (MalformedURLException e) {
//                    e.printStackTrace();
//                    return ResponseEntity.badRequest().body(null);
//                } catch (IOException e) {
//                    e.printStackTrace();
//                    return ResponseEntity.badRequest().body(null);
//                }
//            } else {
//                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(null);
//            }
////        }
//        } else {
//            return ResponseEntity.notFound().build();
//        }
//        return ResponseEntity.notFound().build();
//    }

    //预览。。。(没实现)
    @GetMapping("/getFileContent")
    public ResponseEntity<String> getFileContent(@RequestParam("projectId") Long projectId,
                                                 @RequestParam("employerId") Long employerId,
                                                 @RequestParam("employeeId") Long employeeId) throws IOException {
        LambdaQueryWrapper<FileEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FileEntity::getProjectId, projectId);
        queryWrapper.eq(FileEntity::getEmployeeId, employeeId);
        FileEntity fileEntity = fileMapper.selectOne(queryWrapper);

        if (fileEntity != null) {
            Project project = projectService.getById(fileEntity.getProjectId());
            if (project != null && project.getEmployeeId() == employerId) {
                String fileName = fileEntity.getFileName();//basePath
//                File file = new File(String.valueOf(Paths.get("D:/DLSS", fileName)));
                File file = new File(String.valueOf(Paths.get(basePath, fileName)));
                System.out.println("file是："+file);
                byte[] data;
                try (FileInputStream fis = new FileInputStream(file)) {
                    data = new byte[(int) file.length()];
                    System.out.println("data是："+data);
                    fis.read(data);
                }

                String base64Data = Base64.getEncoder().encodeToString(data);
                System.out.println("base64Data是："+base64Data);
                return ResponseEntity.ok(base64Data);
            }
        }

        return ResponseEntity.ok(null);
    }



//    @GetMapping("/getFileContent")
//    public ResponseEntity<byte[]> getFileContent(@RequestParam("projectId") Long projectId,
//                                                 @RequestParam("employerId") Long employerId,
//                                                 @RequestParam("employeeId") Long employeeId) throws IOException {
////        File file = new File("D:/DLSS/example.txt"); // 文件路径，这里假设是 D 盘下的 DLSS 目录中的 example.txt 文件
//        LambdaQueryWrapper<FileEntity> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(FileEntity::getProjectId,projectId);
//        queryWrapper.eq(FileEntity::getEmployeeId,employeeId);//组员id匹配
//        FileEntity fileEntity = fileMapper.selectOne(queryWrapper);
//        //暂时只能上传和下载一个文件
//        if (fileEntity != null) {
//            // 获取文件的项目信息，包括组长ID
//            Project project = projectService.getById(fileEntity.getProjectId());
//            if (project != null && project.getEmployeeId() == employerId) {
//                // 验证员工是否为项目组长，允许访问文件
//                String fileName = fileEntity.getFileName();
//                File file = new File(String.valueOf(Paths.get("D:/DLSS", fileName)));
//                System.out.println("file是："+file);
//                byte[] data = new byte[(int) file.length()];//Paths.get("D:/DLSS", fileName)
//                System.out.println("data是："+data);
//                try (FileInputStream fis = new FileInputStream(file)) {
//                    fis.read(data);
//                }
//                return ResponseEntity.ok(data);
//            }
//        }
//        return ResponseEntity.ok(null);
//    }

//    @GetMapping("/getFileContent")///{projectId}  ResponseEntity<byte[]>
//    public String getFileContent(@RequestParam("projectId") Long projectId,
//                                                 @RequestParam("employerId") Long employerId,
//                                                 @RequestParam("employeeId") Long employeeId) {
//        System.out.println("getFileContent传来的参数是"+projectId+employerId+employeeId);
//        LambdaQueryWrapper<FileEntity> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(FileEntity::getProjectId,projectId);
//        queryWrapper.eq(FileEntity::getEmployeeId,employeeId);//组员id匹配
//        FileEntity fileEntity = fileMapper.selectOne(queryWrapper);
//        //暂时只能上传和下载一个文件
//        if (fileEntity != null) {
//            // 获取文件的项目信息，包括组长ID
//            Project project = projectService.getById(fileEntity.getProjectId());
//            if (project != null && project.getEmployeeId() == employerId) {
//                // 验证员工是否为项目组长，允许访问文件
//                String fileName = fileEntity.getFileName();
//                try {
//                    // 从本地文件系统读取文件内容
//                    byte[] fileBytes = Files.readAllBytes(Paths.get("D:/DLSS", fileName));
//
//                    HttpHeaders headers = new HttpHeaders();
//                    //设置Content-Disposition为inline表示让浏览器尝试打开文件内容，而不是提示用户下载文件。
//                    // 同时，通过指定filename参数，可以告诉浏览器文件的名称，让浏览器在打开文件时使用该名称。
//                    headers.add("Content-Disposition", "inline; filename=" + fileName);
//                    // 根据文件类型设置不同的Content-Type
//                    System.out.println("fileName是"+fileName);
//                    if (fileName.endsWith(".txt")) {
//                        headers.add("Content-Type", "text/plain; charset=UTF-8");
//                        System.out.println("预览的是.txt文件");
//                    } else if (fileName.endsWith(".doc")) {
//                        System.out.println("预览的是.doc文件");
//                        headers.add("Content-Type", "application/msword");
//                    } else {
//                        System.out.println("预览的是其它文件");
////               设置Content-Type为application/octet-stream可以确保浏览器正确处理二进制流内容，而不会尝试解析或渲染内容
//                        headers.add("Content-Type", "application/octet-stream");
//                    }
//                    System.out.println(ResponseEntity.ok().headers(headers).body(fileBytes)+"是什么");
//                    System.out.println("fileBytes是什么"+fileBytes);
//                    return fileBytes;
////                    return ResponseEntity.ok().headers(headers).body(fileBytes);
//                } catch (IOException e) {
//                    return "";
////                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
//                }
//            }
//        }
//        return "";
////        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
//    }

//    @PostMapping("/txtFile")
//    public String uploadTxtFile(@RequestParam("file") MultipartFile file) {
//        // 处理txt文件上传逻辑
//        // 文件保存等操作
//        System.out.println("uploadTxtFile传来的参数是："+file);
//
//        if (file.isEmpty()) {
//            return "File is empty";
//        }
//
//        // 检查文件类型是否为txt文件
//        if (!file.getContentType().equals("text/plain")) {
//            return "Only txt files are allowed";
//        }
//
//        try {
//            // 保存txt文件到指定路径
//            String fileName = StringUtils.cleanPath(file.getOriginalFilename());
//            Path path = Paths.get(UPLOAD_DIR + fileName);
//            Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
//
//            // 可以在此处进行其他处理，如文件内容读取、解析等
//
//            return "Txt file uploaded successfully!";
//        } catch (IOException e) {
//            return "Failed to upload txt file";
//        }
//    }
}
